﻿using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using Analyzer;
using Analyzer.ViewModel;
using Model;

namespace ReportBrowser.ViewModel
{
    internal class PlacesViewModel : ViewModelBase, IDataErrorInfo
    {
        #region Lifecycle

        public PlacesViewModel(MessagesViewModel messagesProvider)
        {
            this.MessagesProvider = messagesProvider;
            this.PropertyChanged += new PropertyChangedEventHandler(PlacesViewModel_PropertyChanged);
        }

        #endregion Lifecycle

        #region Properties
        //TODO_REVIEW: rename places

        private ActualEntities pContext;
        public ActualEntities Context
        {
            get { return pContext; }
            set
            {
                if (value != pContext)
                {
                    pContext = value;
                    OnPropertyChanged("Context");
                }
            }
        }

        private MessagesViewModel MessagesProvider { get; set; }

        #region Presentation

        private bool pIsCummulative;
        public bool IsCummulative
        {
            get { return pIsCummulative; }
            set
            {
                if (value != pIsCummulative)
                {
                    pIsCummulative = value;
                    OnPropertyChanged("IsCummulative");
                }
            }
        }

        private bool pIsCombined;
        public bool IsCombined
        {
            get { return pIsCombined; }
            set
            {
                if (value != pIsCombined)
                {
                    pIsCombined = value;
                    OnPropertyChanged("IsCombined");
                }
            }
        }

        private ObservableCollection<MessageContainerMemberViewModel> pMembersAboutMessages;
        public ObservableCollection<MessageContainerMemberViewModel> MembersAboutMessages
        {
            get
            {
                if (pMembersAboutMessages == null)
                    pMembersAboutMessages = new ObservableCollection<MessageContainerMemberViewModel>();
                return pMembersAboutMessages;
            }
        }

        private ObservableCollection<MessageContainerTypeViewModel> pTypesAboutMessages;
        public ObservableCollection<MessageContainerTypeViewModel> TypesAboutMessages
        {
            get
            {
                if (pTypesAboutMessages == null)
                    pTypesAboutMessages = new ObservableCollection<MessageContainerTypeViewModel>();
                return pTypesAboutMessages;
            }
        }

        private ObservableCollection<MessageContainerNamespaceViewModel> pNamespacesAboutMessages;
        public ObservableCollection<MessageContainerNamespaceViewModel> NamespacesAboutMessages
        {
            get
            {
                if (pNamespacesAboutMessages == null)
                    pNamespacesAboutMessages = new ObservableCollection<MessageContainerNamespaceViewModel>();
                return pNamespacesAboutMessages;
            }
        }

        private ObservableCollection<MessageContainerModuleViewModel> pModulesAboutMessages;
        public ObservableCollection<MessageContainerModuleViewModel> ModulesAboutMessages
        {
            get
            {
                if (pModulesAboutMessages == null)
                    pModulesAboutMessages = new ObservableCollection<MessageContainerModuleViewModel>();
                return pModulesAboutMessages;
            }
        }

        private int pNOfMembers;
        public int NOfMembers
        {
            get { return pNOfMembers; }
            set
            {
                if (value != pNOfMembers)
                {
                    pNOfMembers = value;
                    OnPropertyChanged("NOfMembers");
                }
            }
        }

        private int pNOfTypes;
        public int NOfTypes
        {
            get { return pNOfTypes; }
            set
            {
                if (value != pNOfTypes)
                {
                    pNOfTypes = value;
                    OnPropertyChanged("NOfTypes");
                }
            }
        }

        private int pNOfNamespaces;
        public int NOfNamespaces
        {
            get { return pNOfNamespaces; }
            set
            {
                if (value != pNOfNamespaces)
                {
                    pNOfNamespaces = value;
                    OnPropertyChanged("NOfNamespaces");
                }
            }
        }

        private int pNOfModules;
        public int NOfModules
        {
            get { return pNOfModules; }
            set
            {
                if (value != pNOfModules)
                {
                    pNOfModules = value;
                    OnPropertyChanged("NOfModules");
                }
            }
        }

        #endregion Presentation

        #endregion Properties

        #region Methods

        public void Refresh()
        {
            if (this.Context != null)
            {
                RefreshMembersAboutMessages();
                RefreshTypesAboutMessages();
                RefreshNamespacesAboutMessages();
                RefreshModulesAboutMessages();
            }
        }

        private void RefreshMembersAboutMessages()
        {
            DispatchService.Dispatch(() =>
                this.MembersAboutMessages.Clear());
            //if (this.IsCombined == false)//&& starting == true
            {
                for (int i = this.MessagesProvider.Model.Count - 1; i > 0
                        && this.MembersAboutMessages.Count < this.NOfMembers; i--)
                {
                    var message = this.MessagesProvider.Model[i];
                    if (message.Member != null
                        && MessageContainerMemberViewModel.HasMessages(message.Member) == true
                        && this.MembersAboutMessages.Any(p => p.Model.Equals(message.Member)) == false)
                        DispatchService.Dispatch(() =>
                            this.MembersAboutMessages.Add(
                                new MessageContainerMemberViewModel(message.Member)));
                }
            }
            //foreach (var message in this.MessagesProvider.Messages)
            //{
            //    if (message.Member != null
            //        && MessageContainerMemberViewModel.HasMessages(message.Member.Model) == true
            //        && this.MembersAboutMessages.Any(p => p.Model.Equals(message.Member.Model)) == false)
            //        this.MembersAboutMessages.Add(
            //            new MessageContainerMemberViewModel(message.Member.Model));
            //}
        }

        private void RefreshTypesAboutMessages(bool starting = false)
        {
            DispatchService.Dispatch(() =>
                this.TypesAboutMessages.Clear());
            //if (this.IsCombined == false)//&& starting == true
            {
                for (int i = this.MessagesProvider.Model.Count - 1; i > 0
                        && this.TypesAboutMessages.Count < this.NOfTypes; i--)
                {
                    var message = this.MessagesProvider.Model[i];
                    if (message.Type != null
                        && MessageContainerTypeViewModel.HasMessages(message.Type) == true
                        && this.TypesAboutMessages.Any(p => p.Model.Equals(message.Type)) == false)
                    {
                        DispatchService.Dispatch(() =>
                            this.TypesAboutMessages.Add(
                                new MessageContainerTypeViewModel(message.Type, this.Context)));
                    }
                }
            }
            //if (this.IsCombined == true && starting == false)
            //this.IsCombined == false && starting == false  is not possible
            //{
            //    foreach (var item in this.MembersAboutMessages)
            //    {
            //        foreach (var message in item.Messages)
            //        {
            //            //if(
            //            //TODO_REVIEW: lehet,hogy a this.IsCombined értelmetlen
            //            //inkább meghagyható minden NOf[...] érték, az helyek súlyai változnak a this.IsCummulative
            //            //hatására, így esetleg változik a sorrend, vagy az összetétel, de továbbra is csak
            //            //megadott számú helyet mutatunk
            //        }
            //    }
            //}
            //foreach (var message in this.MessagesProvider.Messages)
            //{
            //    if (message.Type != null
            //        && MessageContainerTypeViewModel.HasMessages(message.Type.Model) == true
            //        && this.TypesAboutMessages.Any(p => p.Model.Equals(message.Type.Model)) == false)
            //        this.TypesAboutMessages.Add(
            //            new MessageContainerTypeViewModel(message.Type.Model, this.Context));
            //}
        }

        private void RefreshNamespacesAboutMessages(bool starting = false)
        {
            DispatchService.Dispatch(() =>
                this.NamespacesAboutMessages.Clear());
            //if (this.IsCombined == false)//&& starting == true
            {
                for (int i = this.MessagesProvider.Model.Count - 1; i > 0
                        && this.NamespacesAboutMessages.Count < this.NOfNamespaces; i--)
                {
                    var message = this.MessagesProvider.Model[i];
                    if (message.Namespace != null
                        && MessageContainerNamespaceViewModel.HasMessages(message.Namespace) == true
                        && this.NamespacesAboutMessages.Any(p => p.Model.Equals(message.Namespace)) == false)
                        DispatchService.Dispatch(() =>
                            this.NamespacesAboutMessages.Add(
                                new MessageContainerNamespaceViewModel(message.Namespace)));
                }
            }
            //foreach (var message in this.MessagesProvider.Messages)
            //{
            //    if (message.Namespace != null
            //        && MessageContainerNamespaceViewModel.HasMessages(message.Namespace.Model) == true
            //        && this.NamespacesAboutMessages.Any(p => p.Model.Equals(message.Namespace.Model)) == false)
            //        this.NamespacesAboutMessages.Add(
            //            new MessageContainerNamespaceViewModel(message.Namespace.Model));
            //}
        }

        private void RefreshModulesAboutMessages(bool starting = false)
        {
            DispatchService.Dispatch(() =>
                this.ModulesAboutMessages.Clear());
            //if (this.IsCombined == false)//&& starting == true
            {
                for (int i = this.MessagesProvider.Model.Count - 1; i > 0
                    && this.ModulesAboutMessages.Count < this.NOfModules; i--)
                {
                    var message = this.MessagesProvider.Model[i];
                    if (message.Module != null
                        && MessageContainerModuleViewModel.HasMessages(message.Module) == true
                        && this.ModulesAboutMessages.Any(p => p.Model.Equals(message.Module)) == false)
                        DispatchService.Dispatch(() =>
                            this.ModulesAboutMessages.Add(
                                new MessageContainerModuleViewModel(message.Module)));
                }
                //foreach (var message in this.MessagesProvider.Model)
                //{
                //    if (message.Module != null
                //        && MessageContainerModuleViewModel.HasMessages(message.Module) == true
                //        && this.ModulesAboutMessages.Any(p => p.Model.Equals(message.Module)) == false)
                //        this.ModulesAboutMessages.Add(
                //            new MessageContainerModuleViewModel(message.Module));
                //}
            }
        }

        #endregion Methods

        #region EventHandlers

        void PlacesViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "IsCummulative":
                    MessageContainerTypeViewModel.IsCummulative = this.IsCummulative;
                    MessageContainerNamespaceViewModel.IsCummulative = this.IsCummulative;
                    MessageContainerModuleViewModel.IsCummulative = this.IsCummulative;
                    Refresh();
                    break;
                case "NOfMembers":
                    RefreshMembersAboutMessages();
                    break;
                case "NOfTypes":
                    RefreshTypesAboutMessages(starting: true);
                    break;
                case "NOfNamespaces":
                    RefreshNamespacesAboutMessages(starting: true);
                    break;
                case "NOfModules":
                    RefreshModulesAboutMessages(starting: true);
                    break;
                default:
                    break;
            }
        }

        #endregion EventHandlers

        #region IDataErrorInfo Members

        public string Error
        {
            get { throw new NotImplementedException(); }
        }

        public string this[string columnName]
        {
            get
            {
                string msg = null;
                switch (columnName)
                {
                    case "NOfMembers":
                        if (this.NOfMembers < 0)
                            msg = "Nagyobb kell legyen, mint 0 !";
                        break;
                    case "NOfTypes":
                        if (this.NOfTypes < 0)
                            msg = "Nagyobb kell legyen, mint 0 !";
                        break;
                    case "NOfNamespaces":
                        if (this.NOfNamespaces < 0)
                            msg = "Nagyobb kell legyen, mint 0 !";
                        break;
                    case "NOfModules":
                        if (this.NOfModules < 0)
                            msg = "Nagyobb kell legyen, mint 0 !";
                        break;
                    default:
                        throw new ArgumentException(
                            "Unrecognised property " + columnName + " !", "columnName");
                }
                return msg;
            }
        }

        #endregion IDataErrorInfo Members
    }
}
